/*
 *	OpenSource code and fragments by avocado systems, Marcus Fuhrmeister
 *
 *	Redistribution and use in source and binary forms, with or without
 *	modification, are permitted provided that the following conditions
 *	are met:
 *  
 *		* Redistribution of source code must retain the above OpenSource comment,
 *		this list of conditions and the following disclaimer.
 * 
 *		* Redistribution in binary form must reproduce the above OpenSource comment,
 *		this list of conditions and the following disclaimer in the
 *		documentation and/or other materials provided with the distribution.
 * 
 *	Neither the name of 'avocaod systems, Marcus Fuhrmeister' or the
 *	names of contributors may be used to endorse or promote products derived
 *	from this software without specific prior written permission.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 */
package de.fuhrmeister.browserchooser.controller;

import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.TooManyListenersException;

import javax.swing.Icon;

import de.fuhrmeister.browserchooser.model.BrowserModel;
import de.fuhrmeister.browserchooser.model.ModelFactory;
import de.fuhrmeister.browserchooser.view.BrowserShortcutView;
import de.fuhrmeister.util.ConfigManager;
import de.fuhrmeister.util.Tools;

/**
 * Controller class handling the views.
 * 
 * @date 20.11.2008
 * @author Marcus Fuhrmeister
 */
public class BrowserShortcutViewController implements MouseListener, DropTargetListener {

	private static BrowserShortcutViewController self;

	/**
	 * Singleton pattern.
	 * 
	 * @return this
	 */
	public static synchronized BrowserShortcutViewController getInstance() {
		if (self == null) {
			BrowserShortcutViewController.self = new BrowserShortcutViewController();
			return BrowserShortcutViewController.self;
		}
		return BrowserShortcutViewController.self;
	}
	
	/**
	 * Creates a new <code>BrowserShortcutView</code> with the given icon, id and icon size,
	 * registers the listeners and sets a <code>DropTarget</code> on it.
	 * 
	 * @param image the icon for the browser in the dock
	 * @param id the browser id
	 * @param iconsize the icon size
	 * @return BrowserShortcutView
	 */
	public BrowserShortcutView getView(final Icon image, final int id, final int iconsize) {
		final BrowserShortcutView bsv = new BrowserShortcutView(image, id, iconsize);
		bsv.registerListener(this);
		final DropTarget dt = new DropTarget();
		try {
			dt.addDropTargetListener(this);
		} catch (final TooManyListenersException e) {
			e.printStackTrace();
		}
		bsv.setDropTarget(dt);
		return bsv;
	}
	
	/**
	 * BETA
	 * 
	 * Indicates a Drag&Drop gesture on the <code>BrowserShortcutView</code> in the dock.
	 * 
	 * @param source the BrowserShortcutView
	 * @param dragOver true if the dragged object is over the BrowserShortcutView
	 */
	private void indicateDragAndDrop(final BrowserShortcutView source, final boolean dragOver) {
			final int size = Integer.parseInt(Tools.configMng.getPreference(ConfigManager.DOCKLET_ICON_SIZE));
			if (dragOver) {
				((BrowserShortcutView) source).setSize(size+4, size+4);
				((BrowserShortcutView) source).setToolTipText(Tools.configMng.getStringFor(ConfigManager.STRING_TOOLTIP_DRAGDROP_SHORTCUT));
			} else {
				((BrowserShortcutView) source).setSize(size, size);
				((BrowserShortcutView) source).setToolTipText(null);
			}
	}

	public void mouseClicked(final MouseEvent e) {
	}

	public void mouseEntered(final MouseEvent e) {
	}

	public void mouseExited(final MouseEvent e) {
	}

	public void mousePressed(final MouseEvent e) {
	}

	/**
	 * Opens a popup menu, opens a context menu if the browser has more than one version or
	 * calls to open the browser.
	 * 
	 *@param e the mouse event 
	 */
	public void mouseReleased(final MouseEvent e) {
		final BrowserModel bm = ModelFactory.getBrowserModel(((BrowserShortcutView) e.getSource()).getID());
		if (e.isPopupTrigger()) {
			BrowserShortcutViewPopupMenuController.getInstance().show((BrowserShortcutView) e.getSource(), e.getPoint().x, e.getPoint().y, bm.getName(), bm);
		} else {
			if (ModelFactory.modelExists()) {
				if (bm.size() > 1) {
					BrowserShortcutViewPopupMenuController.getInstance().show((BrowserShortcutView) e.getSource(), e.getPoint().x, e.getPoint().y, bm.getName(), bm);
				} else {
					try {
						Tools.browserLauncher.execute(bm.get(0).getExec());
					} catch (final NullPointerException npe) {
						Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
					} catch (final IndexOutOfBoundsException ioobe) {
						Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
					} catch (final IllegalArgumentException iae) {
						Tools.messageBox.inform(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_INFORMATION), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_NOEXECUTABLE));
					}
				}
			} else {
				Tools.messageBox.error(Controller.getInstance().getWindow(Controller.APP_WINDOW_MAIN), Tools.configMng.getStringFor(ConfigManager.MESSAGE_TITLE_ERROR), Tools.configMng.getStringFor(ConfigManager.MESSAGE_VALUE_ERROR_MODELLOADING));
			}
		}
	}
	
	/**
	 * Calls to indicate a drag enter event.
	 * 
	 * @param dtde the DropTargetDragEvent
	 */
	public void dragEnter(DropTargetDragEvent dtde) {
		if (dtde.getDropTargetContext().getComponent() instanceof BrowserShortcutView) {
			this.indicateDragAndDrop((BrowserShortcutView)dtde.getDropTargetContext().getComponent(), true);
			}
	}

	/**
	 * Calls to indicate a drag exit event.
	 * 
	 * @param dtde the DropTargetEvent
	 */
	public void dragExit(DropTargetEvent dte) {
		if (dte.getDropTargetContext().getComponent() instanceof BrowserShortcutView) {
		this.indicateDragAndDrop((BrowserShortcutView)dte.getDropTargetContext().getComponent(), false);
		}
	}

	public void dragOver(DropTargetDragEvent dtde) {
	}

	/**
	 * Calls to indicate a drop event and calls to drop a new version.
	 * 
	 * @param dtde the DropTargetDragEvent
	 */
	public void drop(DropTargetDropEvent dtde) {
		if (dtde.getDropTargetContext().getComponent() instanceof BrowserShortcutView) {
			final BrowserShortcutView bsv = (BrowserShortcutView) dtde.getDropTargetContext().getComponent();
			this.indicateDragAndDrop(bsv, false);
			Controller.getInstance().dropVersion(dtde, bsv.getID());
		}
		
	}

	public void dropActionChanged(DropTargetDragEvent dtde) {
	}
}